package com.yunxin.server.config;


import lombok.RequiredArgsConstructor;
import org.springframework.amqp.core.AcknowledgeMode;
import org.springframework.amqp.rabbit.config.SimpleRabbitListenerContainerFactory;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.connection.ConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.boot.autoconfigure.amqp.RabbitProperties;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author zero°
 * @since 2024-01-02
 */
@Configuration
@RequiredArgsConstructor
public class RabbitAutoConfiguration {

    private final RabbitProperties rabbitProperties;


    @Bean
    public ConnectionFactory connectionFactory() {
        // 初始化RabbitMQ连接配置connectionFactory。
        CachingConnectionFactory connectionFactory = new CachingConnectionFactory ();
        connectionFactory.setHost(rabbitProperties.getHost());
        connectionFactory.setPort(rabbitProperties.getPort());
        connectionFactory.setUsername(rabbitProperties.getUsername());
        connectionFactory.setPassword(rabbitProperties.getPassword());
        // VirtualHost可以在RabbitMQ控制台手动创建，也可以在这里自动创建。
        connectionFactory.setVirtualHost(rabbitProperties.getVirtualHost());
        // 请务必开启Connection自动重连功能，保证服务端发布时客户端可自动重新连接上服务端。
        connectionFactory.getRabbitConnectionFactory().setAutomaticRecoveryEnabled(true);
        /*
         * 使用云消息队列 RabbitMQ，推荐使用CacheMode.CONNECTION 模式（建多个connection，程序会缓存一定数量的connection，每个connection中缓存一定数量的channel）。
         * 云消息队列 RabbitMQ 是集群分布式架构，在CONNECTION模式下，创建多个connection 可以更好地和集群的多个MQ服务节点连接，更高效的发送和消费消息。。
         */
        connectionFactory.setCacheMode(CachingConnectionFactory.CacheMode.CONNECTION);
        // CONNECTION模式下，最大可缓存的connection数量。
        connectionFactory.setConnectionCacheSize(10);
        // CONNECTION模式下，最大可缓存的Channel数量。
        connectionFactory.setChannelCacheSize(64);
        connectionFactory.setPublisherConfirmType(rabbitProperties.getPublisherConfirmType());
        connectionFactory.setPublisherReturns(rabbitProperties.isPublisherReturns());

        // 开启数据传输加密
//        connectionFactory.getRabbitConnectionFactory().useSslProtocol();
//        connectionFactory.setPort(5671);
        return connectionFactory;
    }

    @Bean
    @ConditionalOnClass
    public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(CachingConnectionFactory connectionFactory) {
        SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
        factory.setConnectionFactory(connectionFactory);
        // 自动ack，由spring监测listener代码是否出现异常，没有异常则返回ack；抛出异常则返回nack
        factory.setAcknowledgeMode(AcknowledgeMode.AUTO);
        return factory;
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        // RabbitMQ消息模板，该模板封装了多种常用的消息操作。
        return new RabbitTemplate(connectionFactory);
    }
}
